//
//  BEViewExtension.swift
//  BasicExtensions
//
//  Created by Fanxx on 2018/3/23.
//  Copyright © 2018年 fanxx. All rights reserved.
//


import UIKit

extension UIView {
    /// 视图正在重新布局
    @objc dynamic public var isLayingOut: Bool {
        get { return self.extend["basicExtensions.isLayingOut"] ?? false }
        set { self.extend["basicExtensions.isLayingOut"] = newValue }
    }
    internal class func __beHook() {
        UIView.swizzle(#selector(layoutSubviews), to: #selector(__beLayoutSubviews))
    }
    @objc func __beLayoutSubviews() {
        self.isLayingOut = true
        self.__beLayoutSubviews()
        self.isLayingOut = false
    }
}

// MARK: 位置大小相关信息

extension UIView {
    ///判断刘海屏的安全区域
    public static var safeArea: UIEdgeInsets {
        if #available(iOS 11.0, *) {
            return UIApplication.shared.delegate?.window??.safeAreaInsets ?? .zero
        } else {
            return .zero
        }
    }
    ///视图大小
    public var size: CGSize {
        return self.frame.size
    }
    ///视图宽度
    public var width: CGFloat {
        return self.frame.size.width
    }
    ///视图高度
    public var height: CGFloat {
        return self.frame.size.height
    }
    ///视图位置
    public var origin: CGPoint {
        return self.frame.origin
    }
    ///视图上边距
    public var top: CGFloat {
        return self.frame.origin.y
    }
    ///视图左边距
    public var left: CGFloat {
        return self.frame.origin.x
    }
    ///视图下边距
    public var bottom: CGFloat {
        return (self.superview?.height ?? 0) - self.frame.bottom
    }
    ///视图右边距
    public var right: CGFloat {
        return (self.superview?.width ?? 0) - self.frame.right
    }
}

// MARK: 位移动画等操作

extension UIView {
    ///因为直接设置锚点位置会乱，所以需要同步设置center以修正位置
    ///注意该方法只能在布局确定后才可以使用，或未布局完使用位置照样会乱
    public func anchor(_ anchor: CGPoint) {
        let view = self
        //若未加到父视图则无法生效
        view.superview?.layoutIfNeeded()
        
        let oldOrigin = view.frame.origin
        view.layer.anchorPoint = anchor
        let newOrigin = view.frame.origin
        
        let transition = CGPoint(x: newOrigin.x - oldOrigin.x, y: newOrigin.y - oldOrigin.y)
        
        view.center = .init(view.center.x - transition.x, view.center.y - transition.y)
    }
    ///抖动动画
    public func shake() {
        UIView.animateKeyframes(withDuration: 1, delay: 0, options: UIView.KeyframeAnimationOptions.calculationModeLinear, animations: {
            let left = self.frame.origin.x
            UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration: 0.2, animations: {
                self.frame.origin.x = left - 20
            })
            UIView.addKeyframe(withRelativeStartTime: 0.2, relativeDuration: 0.32, animations: {
                self.frame.origin.x = left + 20
            })
            UIView.addKeyframe(withRelativeStartTime: 0.52, relativeDuration: 0.28, animations: {
                self.frame.origin.x = left - 15
            })
            UIView.addKeyframe(withRelativeStartTime: 0.8, relativeDuration: 0.2, animations: {
                self.frame.origin.x = left
            })
        }, completion: nil)
    }
}

// MARK: 子视图相关操作：查找、定位、标记等

extension UIView {
    ///嵌套循环找到指定的View
    public func forEachAllSubviews<ViewType: UIView>(body: @escaping (ViewType) -> Void) {
        for view in self.subviews {
            if let v = view as? ViewType {
                body(v)
            }
            view.forEachAllSubviews(body: body)
        }
    }
    ///查找第一个指定条件的视图(包含子视图的子视图)
    public func first<ViewType: UIView>(where body: (ViewType) -> Bool) -> UIView? {
        for view in self.subviews {
            if let v = view as? ViewType {
                if body(v) {
                    return v
                }
            }else{
                if let v = view.first(where: body) {
                    return v
                }
            }
        }
        return nil
    }
    ///查找最后一个指定条件的视图(包含子视图的子视图)
    public func last<ViewType: UIView>(where body: (ViewType) -> Bool) -> UIView? {
        for view in self.subviews.reversed() {
            if let v = view as? ViewType {
                if body(v) {
                    return v
                }
            }else{
                if let v = view.last(where: body) {
                    return v
                }
            }
        }
        return nil
    }
    ///清空子Viewigbw
    public func removeAllSubviews() {
        for view in self.subviews {
            view.removeFromSuperview()
        }
    }
    ///获取指定标记的所有子视图(包含子视图的子视图),
    public func viewsWithTag(_ tag: Int) -> [UIView] {
        var views: [UIView] = []
        self.forEachAllSubviews { view in
            if view.tag == tag {
                views.append(view)
            }
        }
        return views
    }
    
    ///获取上一个视图
    @discardableResult
    public func previous() -> UIView?  {
        if let sp = self.superview {
            if let idx = sp.subviews.firstIndex(of: self), idx > 0 {
                return sp.subviews[idx - 1]
            }
        }
        return nil
    }
    
    ///获取下一个视图
    @discardableResult
    public func next() -> UIView? {
        if let sp = self.superview {
            if let idx = sp.subviews.firstIndex(of: self), idx < sp.subviews.count - 1 {
                return sp.subviews[idx + 1]
            }
        }
        return nil
    }
}
extension UIView {
    public func snapshotImage() -> UIImage? {
        UIGraphicsBeginImageContextWithOptions(self.bounds.size, self.isOpaque, 0)
        self.layer.render(in: UIGraphicsGetCurrentContext()!)
        let snap = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return snap
    }
    public func snapshotImage(afterScreenUpdates afterUpdates: Bool) -> UIImage? {
        UIGraphicsBeginImageContextWithOptions(self.bounds.size, self.isOpaque, 0)
        self.drawHierarchy(in: self.bounds, afterScreenUpdates: afterUpdates)
        let snap = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return snap
    }
    public func snapshotPDF() -> Data? {
        var bounds = self.bounds
        let data = NSMutableData()
        guard let consumer = CGDataConsumer(data: data as CFMutableData),
              let context = CGContext(consumer: consumer, mediaBox: &bounds, nil) else {
            return nil
        }
        context.beginPDFPage(nil)
        context.translateBy(x: 0, y: bounds.size.height)
        context.scaleBy(x: 1, y: -1)
        self.layer.render(in: context)
        context.endPDFPage()
        context.closePDF()
        return data as Data
    }
}
